package com.android.GernerateKeySet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.util.Log;

public class CommunicateNFC {

	private final static byte COMMAND_REQUEST = (byte) 0x00;
	private final static byte SET_CERTIFICATE = (byte) 0x01;
	private final static byte REQUEST_DATA = (byte) 0x03; // ������ �ּ��� ��Ź�ϴ� ��������

	private final static byte REQUEST_FILES = (byte) 0x04; // C�� �������� PVKEY �޶�� ���� ��������
	private final static byte CERT_OKAY = (byte) 0x06; //C�� ������ �޶�� ���� ��������
	private final static byte PVKEY_OKAY = (byte) 0x07; // C�� ����Ű �޶�� ���� ��������
	private final static byte FILE_ERROR = (byte) 0x08;
	private final static byte FILE_OKAY = (byte) 0x09;
	public boolean communicate(Intent intent, PreferenceInfo preInfo) {
		/*
		 * �ȵ���̵�� NFC-Forum tag �ν� �ÿ� TAG_DISCOVERED Intent �� �Բ� ��޵˴ϴ�. �� ��
		 * IsoDep Class �� ���ؼ� �� �±׿� I/O�� �����մϴ�.
		 */

		String action = intent.getAction();
		Log.d("*****action",action);
		if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {

			/*
			 * �ν��� Tag�� ���� �� IsoDep ��ü�� ���ɴϴ�. �� ��ü�� I/O�� �����մϴ�.
			 */
			Log.d("NfcAdapter.ACTION_TAG_DISCOVERED",
					"NfcAdapter.ACTION_TAG_DISCOVERED--**");
			Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
			IsoDep isoDep = IsoDep.get(tag);

			if (isoDep != null) {
				try {

					/* ���� */
					isoDep.connect();
					byte[] dataToSend;
					byte[] dataToReceive;

					/*
					 * ��� ����. �ڼ��� ���������� PC���� �����ϴ� ���α׷��� �ҽ��ڵ带 ������ �ּ���.
					 */
					dataToSend = new byte[] { (byte) 0x00, (byte) 0xa4,
							(byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0xe1,
							(byte) 0x04 };
					/*
					 * byte[] transceive(byte[]) �±׷� �����͸� ��� �� ��۹��� ������ �����մϴ�. ��
					 * �Լ��� I/O�� �����մϴ�.
					 */
					dataToReceive = isoDep.transceive(dataToSend);
					Log.d("dataToReceive", "" + byteArrayToHex(dataToReceive));

					dataToSend = new byte[] { (byte) 0x00, (byte) 0xb0,
							(byte) 0x00, (byte) 0x00, (byte) 0x02 };
					dataToReceive = isoDep.transceive(dataToSend);
					Log.d("dataToReceive", "" + byteArrayToHex(dataToReceive));

					dataToSend = new byte[] { (byte) 0x00, (byte) 0xb0,
							(byte) 0x00, (byte) 0x02, (byte) 0x21 };
					// Request command and receive response
					dataToReceive = isoDep.transceive(dataToSend);					
					Log.d("dataToReceive", "" + byteArrayToHex(dataToReceive));
					/*
					 * �� �� ���ĺ��ʹ� ���� �⺻���� NDEF Message�� �ְ� �޾ұ� ������ �����ο� ������� I/O��
					 * �����մϴ�. ���⼭�� ���� ũ���� �����͸� ��۹޾Ƽ� ���Ϸ� �����ϰų� ���Ͽ��� ���� ���� ����ϴ�
					 * �ൿ�� �մϴ�.
					 */
					dataToSend = new byte[] { COMMAND_REQUEST };
					isoDep.transceive(dataToSend);
					Log.d("dataToReceive", "" + byteArrayToHex(dataToReceive));
					

					String path = "/sdcard/cert/";
					int certfile_len = 0;
					int PVfile_len = 0;
					byte[] CertBuffer = null;
					byte[] PVkeyBuffer = null;
					if(preInfo.getPVfile().equals(new String("NULL")) || preInfo.getCertfile().equals(new String("NULL"))){
						/**내장된 인증서가 없거나 인증서 선택하지 않았음**/
						Log.d("Test!!","인증서는 Null입니다");
						dataToSend = new byte[]{FILE_ERROR};
						isoDep.transceive(dataToSend);
					}else{
						dataToSend = new byte[]{FILE_OKAY};
						dataToReceive = isoDep.transceive(dataToSend);
						File PVfile = new File(path+preInfo.getPVfile());
						PVfile_len = (int) PVfile.length();
						PVkeyBuffer = new byte[PVfile_len];
						PVkeyBuffer = getBytesFromFile(PVfile);
						Log.d("PVBYTE","pvkey_Byte : "+byteArrayToHex(PVkeyBuffer));
					
						File Certfile = new File(path+preInfo.getCertfile());
						certfile_len = (int) Certfile.length();
						CertBuffer = new byte[certfile_len];
						CertBuffer = getBytesFromFile(Certfile);
						Log.d("CERT","cert_Byte : "+byteArrayToHex(CertBuffer));
					
						switch (dataToReceive[0]) {
						case SET_CERTIFICATE:
	//						dataToSend = new byte[] { REQUEST_DATA };
	//						dataToReceive = isoDep.transceive(dataToSend);
	//						FileOutputStream outputStream;
	//						outputStream = openFileOutput("certificate",
	//								Context.MODE_PRIVATE);
	//						outputStream.write(dataToReceive);
	//						outputStream.close();
							break;
						case REQUEST_FILES:
	//						Log.d("dataToReceive", "" + byteArrayToHex(CertBuffer));
	//						System.out.println(""+Integer.toHexString(CertBuffer.length));
	//						System.out.println(""+byteArrayToHex(dataToSend));
							
							dataToSend = hexToByteArray(Integer.toHexString(CertBuffer.length));
							dataToReceive =  isoDep.transceive(dataToSend);
							
							
							//������ ���
							int index= 0;
							if(dataToReceive[0] == CERT_OKAY) {
								for(int i = 0; i < certfile_len/256 + 1; i++){
									for(int k = 0; k < dataToSend.length ; k ++){
										dataToSend[k] = '\0';
									}
									
									int j = 0;
									int maxlen = 256;
									if(certfile_len - index < 256){
										maxlen = certfile_len - index;
									}
									dataToSend = new byte[maxlen];
									for (j = 0; j < maxlen; j++) {
										byte temp = CertBuffer[index+j];
										dataToSend[j] = temp;
									}
									dataToReceive = isoDep.transceive(dataToSend);
									index = index + j;
								}
								
							}
							
	
							dataToSend = hexToByteArray(Integer.toHexString(PVkeyBuffer.length));
							dataToReceive =  isoDep.transceive(dataToSend);
							
							//��ȣȭ�� pv key ���
							index= 0;
							if(dataToReceive[0] == PVKEY_OKAY) {
								for(int i = 0; i < PVfile_len/256 + 1; i++){
									for(int k = 0; k < dataToSend.length ; k ++){
										dataToSend[k] = '\0';
									}
									
									int j = 0;
									int maxlen = 256;
									if(PVfile_len - index < 256){
										maxlen = PVfile_len - index;
									}
									dataToSend = new byte[maxlen];
									for (j = 0; j < maxlen; j++) {
										byte temp = PVkeyBuffer[index+j];
										dataToSend[j] = temp;
									}
									dataToReceive = isoDep.transceive(dataToSend);
									index = index + j;
								}
							}
							break;
						}
					}
				} catch (IOException e) {
					System.out.println("IOException");
					e.printStackTrace();
					return true;
				} finally {
					try {
						isoDep.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		return true;
	}
	
	
	
	

	private static byte[] getBytesFromFile(File file) throws IOException {
		InputStream is = new FileInputStream(file);

		// Get the size of the file
		long length = file.length();
		Log.d("length", "" + length);
		if (length > Integer.MAX_VALUE) {
			// File is too large
		}

		byte[] bytes = new byte[(int) length];

		int offset = 0;
		int numRead = 0;
		while (offset < bytes.length
				&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
			offset += numRead;
		}

		if (offset < bytes.length) {
			throw new IOException("Could not completely read file "
					+ file.getName());
		}

		is.close();
		return bytes;
	}

	// hex to byte[]
	private static byte[] hexToByteArray(String hex) {
		byte[] ba;
		if (hex == null || hex.length() == 0)
			return null;
		if (hex.length() % 2 == 0) {
			ba = new byte[hex.length() / 2];
			for (int i = 0; i < ba.length; i++)
				ba[i] = (byte) Integer.parseInt(
						hex.substring(2 * i, 2 * i + 2), 16);
		} else {
			ba = new byte[hex.length() / 2 + 1];
			for (int i = 0; i < ba.length - 1; i++)
				ba[i] = (byte) Integer.parseInt(
						hex.substring(2 * i, 2 * i + 2), 16);
			ba[ba.length - 1] = (byte) Integer.parseInt(
					"0" + hex.substring(hex.length() - 1, hex.length()), 16);
		}
		return ba;
	}

	// byte[] to hex
	private static String byteArrayToHex(byte[] ba) {
		if (ba == null || ba.length == 0)
			return null;
		StringBuffer sb = new StringBuffer(ba.length * 2);
		String hexNumber;
		for (int x = 0; x < ba.length; x++) {
			hexNumber = "0" + Integer.toHexString(0xff & ba[x]);
			sb.append(" 0x" + hexNumber.substring(hexNumber.length() - 2));
		}
		return sb.toString();
	}

	
}
